package com.sxt.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

import org.junit.Test;

import com.sxt.bean.User;

public class Demo1 {
	/**
	 * 获得Class对象的三种方式
	 * 
	 * @throws ClassNotFoundException
	 */
	@Test
	public void test1() throws ClassNotFoundException {
		Class<?> class1 = Class.forName("com.sxt.bean.User");
		Class<?> class2 = com.sxt.bean.User.class;
		Class<?> class3 = new com.sxt.bean.User().getClass();

		System.out.println("class1:" + class1);
		System.out.println("class2:" + class2);
		System.out.println("class3:" + class3);
	}

	/**
	 * 通过反射获得一个类的所有构造方法 再获得其参数类型
	 * 
	 * @throws ClassNotFoundException
	 */
	@Test
	public void test2() throws ClassNotFoundException {
		Class<?> clazz = Class.forName("com.sxt.bean.User");
		Constructor<?>[] cons = clazz.getConstructors();
		for (Constructor<?> constructor : cons) {
			Object[] obj = constructor.getParameterTypes();
			System.out.println(Arrays.toString(obj));
		}
	}

	/**
	 * 通过获得某个构造方法，创建对象
	 * 
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@Test
	public void test3() throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		Class<?> clazz = Class.forName("com.sxt.bean.User");
		Constructor<?> cons = clazz.getConstructor(String.class, int.class,
				boolean.class);
		User user = (User) cons.newInstance("张三", 25, true);
		System.out.println(user);
	}

	/**
	 * 以后一个字节码文件，分析其构造函数
	 * 
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@Test
	public void test4() throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		Class<?> clazz = Class.forName("com.sxt.A");
		Constructor<?>[] cons = clazz.getConstructors();
		for (Constructor<?> constructor : cons) {
			Object[] obj = constructor.getParameterTypes();
			System.out.println(Arrays.toString(obj));
		}

		Constructor<?> con = null;

		con = clazz.getConstructor(double.class, float.class);
		System.out.println(con.newInstance(12.101, 11.1f));

		con = clazz.getConstructor(int.class, String.class, int.class);
		System.out.println(con.newInstance(15, "Hi", 50));

		con = clazz.getConstructor(Date.class, String.class);
		System.out.println(con.newInstance(new Date(), "Hello"));
	}

	/**
	 * 利用反射拿到方法并
	 * 
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@Test
	public void test5() throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		Class<?> clazz = Class.forName("com.sxt.bean.User");
		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			System.out.println(method.getReturnType() + " " + method.getName()
					+ Arrays.toString(method.getParameterTypes()));
		}

		Method m1 = clazz.getMethod("info", String.class);
		Constructor<?> con = clazz.getConstructor(String.class, int.class,
				boolean.class);
		User user = (User) con.newInstance("张三", 23, true);
		String param = (String) m1.invoke(user, "Hello");
		System.out.println(param);

		Method m2 = clazz.getDeclaredMethod("eat", String.class);
		m2.setAccessible(true);
		m2.invoke(user, "饭");
	}

	/**
	 * 操作属性
	 * @throws Exception
	 */
	@Test
	public void test6() throws Exception {
		Class<?> clazz = Class.forName("com.sxt.bean.User");

		Constructor<?> con = clazz.getConstructor(String.class, int.class,
				boolean.class);
		User user = (User) con.newInstance("张三", 23, true);
		
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		
		Field f1 = clazz.getField("isStudent");
		f1.setBoolean(user, false);
		System.out.println(user.isStudent);
		
		Field f2 = clazz.getDeclaredField("name");
		f2.setAccessible(true);
		f2.set(user, "李四");
		System.out.println(user.getName());
	}
}
